/**
 * @file user_wifi.c
 * @brief WiFi功能实现
 * 
 * 实现WiFi连接、重连逻辑和状态管理。
 */

#include "user_wifi.h"
#include "user_config.h"
#include "log_utils.h"
#include "esp_log.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "freertos/event_groups.h"
#include "nvs_flash.h"

static const char *TAG = "user_wifi";

// WiFi事件组
static EventGroupHandle_t wifi_event_group;
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT      BIT1

// WiFi连接相关变量
static int s_retry_num = 0;
static bool wifi_connected = false;

// 函数声明
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                              int32_t event_id, void* event_data);

/**
 * @brief 初始化WiFi
 * 
 * 初始化WiFi模块，创建网络接口并启动连接过程。
 */
void user_wifi_init(void)
{
    // 创建事件组
    wifi_event_group = xEventGroupCreate();
    
    // 初始化网络接口
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_sta();

    // 初始化WiFi
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    // 注册WiFi事件处理函数
    esp_event_handler_instance_t instance_any_id;
    esp_event_handler_instance_t instance_got_ip;
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &wifi_event_handler,
                                                        NULL,
                                                        &instance_any_id));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                        IP_EVENT_STA_GOT_IP,
                                                        &wifi_event_handler,
                                                        NULL,
                                                        &instance_got_ip));

    // 配置WiFi
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = CONFIG_WIFI_SSID,
            .password = CONFIG_WIFI_PASSWORD,
            .threshold.authmode = WIFI_AUTH_WPA2_PSK,
            .sae_pwe_h2e = WPA3_SAE_PWE_BOTH,
        },
    };
    
    ESP_LOGI(TAG, "正在连接WiFi SSID: %s", CONFIG_WIFI_SSID);
    
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());
}

/**
 * @brief WiFi事件处理函数
 * 
 * 处理WiFi连接、断开等事件。
 */
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                              int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        wifi_connected = false;
        if (s_retry_num < CONFIG_WIFI_MAXIMUM_RETRY) {
            esp_wifi_connect();
            s_retry_num++;
            ESP_LOGI(TAG, "WiFi连接失败，正在重试 (%d/%d)", s_retry_num, CONFIG_WIFI_MAXIMUM_RETRY);
        } else {
            xEventGroupSetBits(wifi_event_group, WIFI_FAIL_BIT);
            ESP_LOGE(TAG, "WiFi连接失败，已达到最大重试次数");
        }
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "获得IP地址:" IPSTR, IP2STR(&event->ip_info.ip));
        s_retry_num = 0;
        wifi_connected = true;
        xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT);
    }
}

/**
 * @brief 等待WiFi连接
 * 
 * 等待WiFi连接成功或超时。
 * 
 * @param ticks_to_wait 等待的ticks数
 * @return bool true表示连接成功，false表示超时或失败
 */
bool user_wifi_wait_for_connection(TickType_t ticks_to_wait)
{
    EventBits_t bits = xEventGroupWaitBits(wifi_event_group,
            WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
            pdFALSE,
            pdFALSE,
            ticks_to_wait);

    if (bits & WIFI_CONNECTED_BIT) {
        ESP_LOGI(TAG, "WiFi连接成功");
        return true;
    } else if (bits & WIFI_FAIL_BIT) {
        ESP_LOGE(TAG, "WiFi连接失败");
        return false;
    } else {
        ESP_LOGE(TAG, "WiFi连接超时");
        return false;
    }
}

/**
 * @brief 检查WiFi连接状态
 * 
 * @return bool true表示已连接，false表示未连接
 */
bool user_wifi_is_connected(void)
{
    return wifi_connected;
}

/**
 * @brief 断开WiFi连接
 * 
 * 主动断开WiFi连接。
 */
void user_wifi_disconnect(void)
{
    esp_wifi_disconnect();
    wifi_connected = false;
    ESP_LOGI(TAG, "WiFi已断开");
}

/**
 * @brief 重新连接WiFi
 * 
 * 重新连接到WiFi网络。
 */
void user_wifi_reconnect(void)
{
    s_retry_num = 0;
    esp_wifi_connect();
    ESP_LOGI(TAG, "正在重新连接WiFi");
}